home *** CD-ROM | disk | FTP | other *** search
- #include "modern.h"
- #ifdef MODERN
- # include <stdlib.h>
- # include <string.h>
- # ifdef ZMEM
- # define MEMCPY(d,s,n) strcpy(d,s)
- # endif
- # ifdef NOMEMCPY
- # define MEMCPY(d,s,n) strcpy(d,s)
- # endif
- # ifndef MEMCPY
- # define MEMCPY(d,s,n) memcpy(d,s,n)
- # endif
- # ifdef __TURBOC__
- # include <io.h>
- # endif
- #else
- # define MEMCPY(d,s,n) strcpy(d,s)
- char *strcpy(), *getenv(), *malloc(), *realloc();
- int strlen();
- #endif
- #include <stdio.h>
- #include "define.h"
- #include "lzwbits.h"
-
- #ifdef MSDOS
- # define switchar(c) ((c)=='-' || (c)=='/')
- #else
- # define switchar(c) ((c)=='/')
- #endif
-
- void revector(argc, argv, n)
- char ***argv;
- {
- register i;
-
- /* create new argument vector */
- i = (int)((argc + n) * sizeof(char *));
- if (argvector) {
- free(argvector);
- if ((argvector=(char**)realloc(argvector, i)) == NULL) outmem(stderr);
- } else {
- argvector = (char **)salloc(i);
- /* copy origin arguments */
- for (i=0; i<argc; i++) argvector[i] = (*argv)[i];
- }
- *argv = argvector;
- }
-
- int buildarg(argc, argv, buf)
- char ***argv, *buf;
- {
- register c;
- register i, n;
-
- i = 0; n = 0;
- while (buf[i]) { /* count number of words in responce file */
- while ((c=buf[i])!='\0' && space(c)) ++i;
- if (buf[i]) ++n; /* next word found */
- while ((c=buf[i])!='\0' && !space(c)) ++i;
- }
- revector(argc, argv, n);
- i = argc; n = 0;
- while (buf[n]) {/* append new arguments */
- while ((c=buf[n])!='\0' && space(c)) buf[n++] = '\0';
- if (buf[n]) argvector[i++] = buf+n; /* next word found */
- while ((c=buf[n])!='\0' && !space(c)) ++n;
- }
- return i;
- }
-
- #define INDMAX 32760
- #define INDMIN 1024
- #define INDLOW 1023
-
- int argfile(argc, argv, fname, buf)
- char ***argv, *fname, **buf;
- {
- register i;
- register l = 0;
- register char *p = NULL;
-
- if (fname[0] == '-' && fname[1] == '\0') {
- /* standard input */ i = 0;
- } else if ((i = open(fname, OM_RDONLY)) < 0 || fstat(i, &st) < 0) {
- (void)fprintf(stderr, "Tar: can\'t process \'%s\'\n", fname);
- done(ERRARG);
- }
- if ((st.st_mode & S_IFMT) == S_IFREG) {
- if (st.st_size >= INDMAX) {
- (void)fprintf(stderr, "Tar: \'%s\' exceeds limit in size\n", fname);
- done(ERRARG);
- }
- p = salloc((l = (int)st.st_size) + 1);
- /* Note: effective text file size differs from the real one under MS-DOS */
- if ((l = read(i, p, l)) < 1) {
- (void)fprintf(stderr, "Tar: can\'t read \'%s\'\n", fname);
- done(ERRARG);
- }
- (void)close(i);
- } else if ((st.st_mode & S_IFMT) == S_IFCHR || /* character device */
- (st.st_mode & S_IFMT) == S_IFIFO) { /* pipe */
- int j, m; long s;
-
- for (s=0, m=INDMAX+1; m>=INDMIN; ) {
- if ((p = malloc(m)) != NULL) goto ok;
- m = ((m+INDLOW) & ~INDLOW) / 2;
- }
- outmem(stderr);
- ok:
- s = 0;
- do {
- l = (int)s;
- j = read(i, p+l, m-l);
- s += j;
- } while (j>0 && s<m);
- if (j < 0) {
- (void)fprintf(stderr, "Tar: error reading \'%s\'\n", fname);
- done(ERRARG);
- }
- if (s >= m) {
- if (m < INDMAX) {
- outmem(stderr);
- } else {
- (void)fprintf(stderr,"Tar: \'%s\' exceeds limit in size\n",fname);
- done(ERRARG);
- }
- }
- if (l+1 < m) {
- free(p);
- if ((p = realloc(p, l+1)) == NULL) {
- (void)fprintf(stderr, "Tar: error shrinking memory block\n");
- done(ERRARG);
- }
- }
- } else {
- (void)fprintf(stderr, "Tar: \'%s\' not a file\n", fname);
- done(ERRARG);
- }
- p[l] = '\0';
- return buildarg(argc, argv, (*buf=p));
- }
-
- int envbuild(argc, argv)
- char ***argv;
- {
- register i;
- register char *p;
-
- if ((p = getenv("TARCMD")) == NULL) return 0;
- i = strlen(p); if (!i) return 0;
- #ifdef UNIX
- # define ARGFILE
- if (p[0] == '/')
- #endif
- #ifdef MSDOS
- # define ARGFILE
- if (((p[0] <= 'A' && p[0] >= 'Z') || (p[0] <= 'a' && p[0] >= 'z')) &&
- p[1] == ':' && p[2] == '\\' || p[0]=='\\')
- #endif
- #ifdef ARGFILE
- return argfile(argc, argv, p, &tarcmd);
- #endif
- #if 0 /*ndef MSDOS*/
- /* Make a copy of environment variable to avoid protection problems */
- tarcmd = salloc(i+1); (void)MEMCPY(tarcmd, p, i+1); p = tarcmd;
- #endif
- return buildarg(argc, argv, p);
- }
-
- /* ARGSUSED */ static void readblk(p, argv, i)
- char **p, **argv; int *i;
- {
- register char *s;
- register n;
-
- if (cblock) {
- (void)fprintf(stderr, "Tar: blocksize multiply defined\n");
- done(ERRARG);
- }
- s = argv[++*i];
- for (cblock=0,n=0; digit(*s) && n<3; ++n,s++) cblock = *s-'0' + 10*cblock;
- if (n>0 && n<=2) {
- if (*s == 'k' || *s == 'K') { cblock *= 2; s++; }
- else if (*s == 'b' || *s == 'B') s++;
- if (*s=='\0' && cblock>0 && cblock<=MAXBLOCK) /* blocksize ok */ return;
- }
- (void)fprintf(stderr, "Tar: bad blocksize (max is %d)\n", MAXBLOCK);
- done(ERRARG);
- #ifdef __TURBOC__
- (void)p;
- #endif
- }
-
- #ifdef MSDOS
- static void readvol(p, argv, i)
- char **p, **argv; int *i;
- {
- register char *s;
- register n;
-
- if (k_flag || tapename) {
- (void)fprintf(stderr, "Tar: tape device multiply defined\n");
- done(ERRARG);
- }
- k_flag = TRUE;
- s = argv[++*i];
- for (volume=0, n=0; digit(*s) && n<7; ++n,s++) volume = *s-'0' + 10*volume;
- if (n>0 && n<=6) {
- if (*s == 'm' || *s == 'M') { volume <<= 11; ++s; }
- else if (*s == 'k' || *s == 'K') { volume += volume; ++s; }
- else if (*s == 'b' || *s == 'B') ++s;
- else volume += volume;
- if ((volume & ~0x7FFE) == 0)
- if (*s=='\0' && argdisk((int)volume >> 1) == 0)
- /* diskette size ok */ return;
- }
- (void)fprintf(stderr, "Tar: Invalid diskette size\n");
- done(ERRARG);
- #ifdef __TURBOC__
- (void)p;
- #endif
- }
- #endif
-
- /* ARGSUSED */ static void readpk(p, argv, i)
- char **p, **argv; int *i;
- {
- register c;
- c = (*p)[0]; if (c>='A' && c<='Z') c += 'z'-'Z';
-
- if (pktype != PKNONE) {
- (void)fprintf(stderr,"Tar: compression method multiply defined\n");
- done(ERRARG);
- }
- if (c == 'z' || c == ',') {
- pktype = c==',' ? PKpLZW : PKfLZW;
- lzwbits = BITS;
- if ((*p)[1] == '9') {
- *p += 1; lzwbits = 9;
- } else if ((*p)[1] == '1') {
- *p += 2; lzwbits = 10 + **p - '0';
- if (lzwbits < 10 || lzwbits > BITS) {
- (void)fprintf(stderr, "Tar: Invalid bits factor\n");
- done(ERRARG);
- }
- }
- } else {
- pktype = c=='.' ? PKZIP : PKDEF;
- ziplevel = 6; /* default */
- if (digit((*p)[1])) {
- *p += 1; ziplevel = **p - '0';
- }
- }
- #ifdef __TURBOC__
- (void)argv; (void)i;
- #endif
- }
-
- #ifdef MSDOS
- /* ARGSUSED */ static void devno(p, argv, i)
- char **p, **argv; int *i;
- {
- ndrive = **p & 7; setdrive = TRUE;
- #ifdef __TURBOC__
- (void)argv; (void)i;
- #endif
- }
- #endif
-
- static void readxcl(p, argv, i)
- char **p, **argv; int *i;
- {
- if (xcnt >= XMAX) {
- (void)fprintf(stderr,"Tar: too many \'%s\'s\n", **p ? "#" : argv[*i]);
- done(ERRARG);
- }
- xarg[xcnt++] = argv[++*i];
- }
-
- #define TO_APP '\377'
- #define TO_INC '\376'
- #define TO_REM '\375'
- #define TO_CALL '\374'
- #define MAXOPT 8
-
- /* Number of compiles does not allow correct union initialization,
- that's why I have to use this ugly nested structure. */
- static struct {
- struct {
- void (*fun) __ARGS__((char**, char**, int*));
- char *x;
- } p;
- char longop[MAXOPT], shortop;
- char optype, xflag;
- } oplist[] = {
- {{NULL, &a_flag}, "append", 'a', TRUE, 0},
- {{NULL, &a_flag}, "append", 'r', TRUE, 0},
- {{NULL, &c_flag}, "create", 'c', TRUE, 0},
- {{NULL, &x_flag}, "extract", 'x', TRUE, 0},
- {{NULL, &t_flag}, "list", 't', TO_INC, 0},
- {{NULL, &y_flag}, "move", 'y', TRUE, 0},
- {{NULL, &u_flag}, "update", 'u', TRUE, 0},
- {{NULL, &d_flag}, "delete", 'd', TRUE, 0},
- {{NULL, &v_flag}, "verbose", 'v', TO_INC, 0},
- {{NULL, &w_flag}, "interact", 'w', TRUE, 0},
- {{NULL, &i_flag}, "inhibit", 'i', TRUE, 0},
- {{NULL, &s_flag}, "strict", 's', TRUE, 0},
- {{NULL, &m_flag}, "modifica", 'm', TRUE, 0},
- {{NULL, &j_flag}, "comment", 'j', TRUE, 0},
- {{NULL, &nonest}, "nonest", 'n', TRUE, 0},
- {{NULL, &o_flag}, "", 'o', TRUE, 0},
- #ifdef UNIX
- {{NULL, &dslash}, "", '/', TRUE, 0},
- {{NULL, &l_flag}, "link-war", 'l', TRUE, 0},
- {{NULL, &p_flag}, "permissi", 'p', TRUE, 0},
- {{NULL, &ndrive}, "", '0', 0, 0},
- {{NULL, &ndrive}, "", '1', 1, 0},
- {{NULL, &ndrive}, "", '2', 2, 0},
- {{NULL, &ndrive}, "", '3', 3, 0},
- {{NULL, &ndrive}, "", '4', 4, 0},
- {{NULL, &ndrive}, "", '5', 5, 0},
- {{NULL, &ndrive}, "", '6', 6, 0},
- {{NULL, &ndrive}, "", '7', 7, 0},
- #endif
- #ifdef MSDOS
- {{NULL, &dslash}, "", '\\',TRUE, 0},
- {{NULL, &l_flag}, "link-cop", 'l', TRUE, 0},
- {{readvol, NULL}, "", 'k', TO_CALL, 0},
- {{NULL, &deldrv}, "", ':', TRUE, 0},
- {{devno, NULL}, "", '0', TO_CALL, 0},
- {{devno, NULL}, "", '1', TO_CALL, 0},
- {{devno, NULL}, "", '2', TO_CALL, 0},
- {{devno, NULL}, "", '3', TO_CALL, 0},
- #endif
- {{NULL, (char*)&tapename}, "file", 'f', TO_REM, 0},
- {{readblk, NULL}, "block-si", 'b', TO_CALL, 0},
- {{NULL, NULL}, "", '@', TO_APP, 0},
- {{readxcl, NULL}, "exclude", '#', TO_CALL, 0},
- {{readpk, NULL}, "", ',', TO_CALL, 0},
- {{readpk, NULL}, "", '.', TO_CALL, 0},
- {{readpk, NULL}, "", 'e', TO_CALL, 0},
- {{readpk, NULL}, "", 'z', TO_CALL, 0},
- {{NULL, &pktype}, "compress", 0, PKpLZW, 0},
- {{NULL, &pktype}, "zip-arch", 0, PKZIP, 0},
- {{NULL, &pktype}, "zip-file", 0, PKDEF, 0},
- {{NULL, &gnuzip}, "gzip", 0, TRUE, 0},
- {{NULL, &gnuzip}, "gnu", 0, TRUE, 0},
- };
-
- void cleanopt()
- {
- register i;
- for (i=0; i<dimof(oplist); i++) {
- switch (oplist[i].optype) {
- case TO_REM: *(char**)(oplist[i].p.x) = NULL;
- case TO_CALL: break;
- default: *(oplist[i].p.x) = 0;
- }
- oplist[i].xflag = 0;
- }
- }
-
- static void cmpflags __ARGS__((char**, int, int));
-
- static void cmpflags(fl, n, to_break)
- char *fl[];
- {
- register i;
- register x0, x1;
-
- for (x0=x1=0, i=0; i<n; i++) {
- if (*(fl[i])) { if (*(fl[i]) & OPTFLAG) ++x1; else ++x0; }
- }
- if (x0 == 1) {
- for (i=0; i<n; i++) if (*(fl[i]) & OPTFLAG) *(fl[i]) = 0;
- } else if (x0>1 || x1>1) {
- (void)fprintf(stderr, "Tar: ambiguous options\n");
- if (to_break) done(ERRARG);
- }
- }
-
- int readopt(argc, argv, aux)
- int *argc; char ***argv;
- {
- register c;
- register j, k;
- char lex[MAXOPT];
- char *p;
- int i;
- char *fl[5];
-
- if (*argc < 1) {
- (void)fprintf(stderr, "Tar: no options to read\n");
- done(ERRARG);
- }
- for (i=0; i<*argc; i++) {
- p = (*argv)[i];
- if (switchar(*p)) {
- if (p[1] == '\0') goto end;
- if (p[1] != '-' || p[0] != '-') ++p;
- } else if (*p != '+' && i) goto end;
-
- if (p[0]!='+' && (p[0]!='-' || p[1]!='-')) {
- for (;*p; p++) {
- c = *p; if (switchar(c)) goto end;
- if (c>='A' && c<='Z') c += 'z'-'Z';
- for (k=0; k<dimof(oplist); k++) {
- if (c == oplist[k].shortop) goto sfound;
- }
- (void)fprintf(stderr, "Tar: bad option \'%c\'\n", *p);
- done(ERRARG);
- sfound: switch (oplist[k].optype) {
- case TO_APP:
- if (aux) {
- appname = (*argv)[++i];
- } else {
- *argc = argfile(*argc, argv, (*argv)[++i], &responce);
- }
- break;
- case TO_REM:
- if (*(oplist[k].p.x) && oplist[k].xflag == aux) {
- (void)fprintf(stderr,"Tar: duplicate \'%c\'\n",*p);
- done(ERRARG);
- }
- *(char**)(oplist[k].p.x) = (*argv)[++i];
- break;
- case TO_CALL:
- (*(oplist[k].p.fun))(&p, (*argv), &i);
- break;
- case TO_INC:
- if (oplist[k].xflag != aux) *(oplist[k].p.x) = 0;
- *(oplist[k].p.x) = aux | (1 + *(oplist[k].p.x));
- break;
- default:
- if (*(oplist[i].p.x) && oplist[k].xflag == aux) {
- (void)fprintf(stderr,"Tar: duplicate \'%c\'\n",*p);
- done(ERRARG);
- }
- *(oplist[k].p.x) = aux | oplist[k].optype;
- }
- oplist[k].xflag = aux;
- }
- } else {
- if (p[0] == '+') p += 1; else p += 2;
- for (j=0; *p; p++) {
- if (j < MAXOPT) {
- c = *p; if (c>='A' && c<='Z') c += 'z'-'Z';
- lex[j++] = c;
- }
- }
- if (!j) goto end;
- for (k=0; k<dimof(oplist); k++) {
- if (oplist[k].longop[0] &&
- 0 == strncmp(oplist[k].longop, lex, j)) goto lfound;
- }
- (void)fprintf(stderr, "Tar: bad option \'%s\'\n", (*argv)[i]);
- done(ERRARG);
- lfound: switch (oplist[k].optype) {
- case TO_APP:
- if (aux) {
- appname = (*argv)[++i];
- } else {
- *argc = argfile(*argc, argv, (*argv)[++i], &responce);
- }
- break;
- case TO_REM:
- if (*(oplist[k].p.x) && oplist[k].xflag == aux) {
- (void)fprintf(stderr, "Tar: duplicate \'%s\'\n", (*argv)[i]);
- done(ERRARG);
- }
- *(char**)(oplist[k].p.x) = (*argv)[++i];
- break;
- case TO_CALL:
- (*(oplist[k].p.fun))(&p, (*argv), &i);
- break;
- case TO_INC:
- if (oplist[k].xflag != aux) *(oplist[k].p.x) = 0;
- *(oplist[k].p.x) = aux | (1 + *(oplist[k].p.x));
- break;
- default:
- if (*(oplist[k].p.x) && oplist[k].xflag == aux) {
- (void)fprintf(stderr,
- "Tar: duplicate \'%s\'\n", (*argv)[i]);
- done(ERRARG);
- }
- *(oplist[k].p.x) = oplist[k].optype;
- }
- oplist[k].xflag = aux;
- }
- }
- end:
- fl[0] = &c_flag; fl[1] = &u_flag; cmpflags(fl, 2, TRUE);
- fl[0] = &a_flag; fl[1] = &x_flag; fl[2] = &t_flag; cmpflags(fl, 3, TRUE);
- fl[0] = &d_flag; fl[3] = &c_flag; cmpflags(fl, 4, TRUE);
- fl[0] = &d_flag; fl[1] = &i_flag; cmpflags(fl, 2, TRUE);
- if (c_flag && !a_flag) a_flag = c_flag;
- if (u_flag && !a_flag && !x_flag) a_flag = u_flag;
- if (a_flag && !c_flag) {
- fl[0] = &a_flag; fl[1] = &i_flag; cmpflags(fl, 2, TRUE);
- }
- fl[0] = &u_flag; fl[1] = &m_flag; cmpflags(fl, 2, FALSE);
- return i;
- }
-